#include "table.h"
#include "qtch/log.h"
#include "qtch/util.h"
#include "qtch/env.h"


static qtch::Logger::ptr logger = QTCH_LOG_NAME("orm");

void test_orm(){
    std::string xmlPath = "/home/qiu/qtch/bin/orm_conf";
    std::vector<std::string> files;
    qtch::FSUtil::listAllFiles(files,xmlPath, ".xml");
    for(size_t i = 0; i < files.size(); ++i){
        qtch::tinyxml2::XMLDocument doc;
        QTCH_LOG_INFO(logger) << "init xml=" << files[i] << " begin";
        if(doc.LoadFile(files[i].c_str())){
            QTCH_LOG_ERROR(logger) << "error:" << doc.ErrorStr();
            continue;
        }
        qtch::orm::Table::ptr table(new qtch::orm::Table());
        if(!table->init(*doc.RootElement())){
            QTCH_LOG_ERROR(logger) << "table init error";
            continue;
        }
        QTCH_LOG_INFO(logger) << "table:\n" << table;

    }
}

/**
set(ORM_CONFIG_DIR "/home/qiu/qtch/orm_conf")
set(ORM_OUT_DIR "/home/qiu/qtch/orm_out")

set(
    ORM_XML
    ${ORM_CONFIG_DIR}/im_user.xml
)

add_custom_command(
    OUTPUT 
        ${LIB_SRC}
    COMMAND 
        /home/qiu/qtch/bin/orm -g ${ORM_CONFIG_DIR} -o ${ORM_OUT_DIR}
    DEPENDS
        qtch
        ${ORM_XML}
    WORKING_DIRECTORY
        ${CMAKE_CURRENT_SOURCE_DIR}
    COMMENT
        "Rebuild orm " ${ORM_XML}
)
 */

void gen_cmake(const std::string& path,const std::vector<qtch::orm::Table::ptr>& tbs,const std::vector<std::string>& xmlFiles){
    std::ofstream ofs(path+"/CMakeLists.txt");
    ofs << "cmake_minimum_required(VERSION 3.0)" << std::endl;
    ofs << "project(orm_data)" << std::endl;
    ofs << std::endl;
    std::string config_path = qtch::EnvMgr::GetInstance()->getAbsolutePath(qtch::EnvMgr::GetInstance()->get("g","./orm_conf"));
    std::string output_path = qtch::EnvMgr::GetInstance()->getAbsolutePath(qtch::EnvMgr::GetInstance()->get("o","./orm_out"));
    ofs << "set(LIB_SRC" << std::endl;
    for(auto& i : tbs){
        std::string namespacePath = qtch::StringUtil::replace(i->getNamespace(),'.',"/");
        ofs << "    "<< output_path << "/" << namespacePath +"/" + qtch::StringUtil::toLower(i->getFileName()) << ".cc" << std::endl;
    }
    ofs << ")" << std::endl;
    ofs << "add_library(orm_data ${LIB_SRC})" << std::endl;


    ofs << "set(ORM_CONFIG_DIR \"" << config_path << "\")" << std::endl;
    ofs << "set(ORM_OUT_DIR \""<< output_path <<"\")" << std::endl;
    ofs << "set(" << std::endl;
    ofs << "    ORM_XML" << std::endl;
    for(size_t i = 0; i< xmlFiles.size(); ++i){
        ofs << "    " << xmlFiles[i] << std::endl;
    }
    ofs << ")" << std::endl;
    ofs << std::endl;
    ofs << "add_custom_command(" << std::endl;
    ofs << "    OUTPUT" << std::endl;
    ofs << "        ${LIB_SRC}" << std::endl;
    ofs << "    COMMAND" << std::endl;
    ofs << "    " << qtch::EnvMgr::GetInstance()->getExe() << " -g ${ORM_CONFIG_DIR} -o ${ORM_OUT_DIR}" << std::endl;
    ofs << "    DEPENDS" << std::endl;
    ofs << "        qtch" << std::endl;
    ofs << "        ${ORM_XML}" << std::endl;
    ofs << "    WORKING_DIRECTORY" << std::endl;
    ofs << "        ${CMAKE_CURRENT_SOURCE_DIR}" << std::endl;
    ofs << "    COMMENT" << std::endl;
    ofs << "        \"Rebuild orm \" ${ORM_XML}" << std::endl;
    ofs << ")" << std::endl;
    ofs << std::endl;



}

void gen_table(std::string input_path,std::string out_path){
    std::vector<std::string> files;
    qtch::FSUtil::listAllFiles(files,input_path, ".xml");
    std::vector<qtch::orm::Table::ptr> tbs;
    std::vector<std::string> xmlFiles;
    for(size_t i = 0; i < files.size(); ++i){
        qtch::tinyxml2::XMLDocument doc;
        QTCH_LOG_INFO(logger) << "init xml=" << files[i] << " begin";
        int rt = doc.LoadFile(files[i].c_str());
        if(rt){
            QTCH_LOG_ERROR(logger) << "rt=" << rt << " rtName=" << doc.ErrorIDToName((qtch::tinyxml2::XMLError)rt) << " error=" << doc.ErrorStr() ;
            continue;
        }
        qtch::orm::Table::ptr table(new qtch::orm::Table());
        if(!table->init(*doc.RootElement())){
            QTCH_LOG_ERROR(logger) << "table init error";
            continue;
        }
        xmlFiles.push_back(files[i]);
        table->gen(out_path);
        tbs.push_back(table);

    }
    if(!qtch::EnvMgr::GetInstance()->has("m")){
        gen_cmake(out_path,tbs,xmlFiles);
    }
}


int main(int argc, char** argv){
    qtch::EnvMgr::GetInstance()->addHelp("g"," ormC config path");
    qtch::EnvMgr::GetInstance()->addHelp("o","orm out path");
    qtch::EnvMgr::GetInstance()->addHelp("m","not gen cmake file");
    qtch::EnvMgr::GetInstance()->addHelp("d","debug model");
    qtch::EnvMgr::GetInstance()->addHelp("p","print help");
    if(!qtch::EnvMgr::GetInstance()->init(argc,argv)){
        qtch::EnvMgr::GetInstance()->printfHelp();
        return 0;
    }
    if(qtch::EnvMgr::GetInstance()->has("p")){
        qtch::EnvMgr::GetInstance()->printfHelp();
        return 0;
    }
    if(qtch::EnvMgr::GetInstance()->has("d")){
        logger->setLevel(qtch::LogLevel::DEBUG);
    }else{
        logger->setLevel(qtch::LogLevel::INFO);
    }
    std::string config_path = qtch::EnvMgr::GetInstance()->getAbsolutePath(qtch::EnvMgr::GetInstance()->get("g","./orm_conf"));
    std::string output_path = qtch::EnvMgr::GetInstance()->getAbsolutePath(qtch::EnvMgr::GetInstance()->get("o","./orm_out"));
    
    std::cout << "using orm config path=" << config_path << std::endl;
    std::cout << "using orm config path=" << output_path << std::endl;
    gen_table(config_path,output_path);
}